﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Printing;
using System.Windows;
using System.Windows.Media;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using System.Xml;
namespace WPFExcelReport
{
    public class XpsCreate
    {
        const string packageWithPrintTicketName = "XpsDocument-withPrintTicket.xps";
        const string packageName = @"D:\ITXRPRT\Documents\Print\XpsDocument.xps"; // (without PrintTicket)
        const string image1 = @"D:\ITXRPRT\Documents\Images\picture.jpg";
        const string image2 = @"D:\ITXRPRT\Documents\Images\image.tif";
        const string image3 = @"D:\ITXRPRT\Documents\Images\black.tif";
        const string font1 = @"D:\urwfonts\LetterGothic-Reg.ttf";
        const string font2 = @"D:\urwfonts\LetterGothic-Reg.ttf";
        const string fontContentType =
            "application/vnd.ms-package.obfuscated-opentype";


        // -------------------------------- Run -----------------------------------
        /// <summary>
        ///   Creates two XpsDocument packages, the first without a PrintTicket
        ///   and a second with a PrintTicket.</summary>
        public XpsDocument Run(DataTable tb)
        {
            XpsDocument xpsDocument = null;
            // First, create an XpsDocument without a PrintTicket. - - - - - - - -

            // If the document package exists from a previous run, delete it.
            if (File.Exists(packageName))
                File.Delete(packageName);

            //<SnippetXpsCreatePackageOpen>
            // Create an XpsDocument package (without PrintTicket).
            using (Package package = Package.Open(packageName))
            {
                  xpsDocument = new XpsDocument(package);

                // Add the package content (false=without PrintTicket).
                AddPackageContent(tb, xpsDocument, false);

                // Close the package.
                xpsDocument.Close();
            }
            return xpsDocument;

        }// end:Run()


        //<SnippetXpsCreateAddPkgContent>
        // ------------------------- AddPackageContent ----------------------------
        /// <summary>
        ///   Adds a predefined set of content to a given XPS document.</summary>
        /// <param name="xpsDocument">
        ///   The package to add the document content to.</param>
        /// <param name="attachPrintTicket">
        ///   true to include a PrintTicket with the
        ///   document; otherwise, false.</param>
        private void AddPackageContent(DataTable tb, XpsDocument xpsDocument, bool attachPrintTicket)
        {
            try
            {
                PrintTicket printTicket = GetPrintTicketFromPrinter();
                // PrintTicket is null, there is no need to attach one.
                if (printTicket == null)
                    attachPrintTicket = false;

                // Add a FixedDocumentSequence at the Package root
                IXpsFixedDocumentSequenceWriter documentSequenceWriter =
                    xpsDocument.AddFixedDocumentSequence();

                // Add the 1st FixedDocument to the FixedDocumentSequence. - - - - -
                IXpsFixedDocumentWriter fixedDocumentWriter =
                    documentSequenceWriter.AddFixedDocument();

                // Add content to the 1st document
                AddDocumentContent(tb, fixedDocumentWriter);

                // Commit the 1st Document
                fixedDocumentWriter.Commit();

                // Add a 2nd FixedDocument to the FixedDocumentSequence. - - - - - -
                fixedDocumentWriter = documentSequenceWriter.AddFixedDocument();

                // Add content to the 2nd document.
                AddDocumentContent(tb, fixedDocumentWriter);

                // If attaching PrintTickets, attach one at the FixedDocument level.
                if (attachPrintTicket)
                    fixedDocumentWriter.PrintTicket = printTicket;

                // Commit the 2nd document.
                fixedDocumentWriter.Commit();

                // If attaching PrintTickets, attach one at
                // the package FixedDocumentSequence level.
                if (attachPrintTicket)
                    documentSequenceWriter.PrintTicket = printTicket;

                // Commit the FixedDocumentSequence
                documentSequenceWriter.Commit();
            }
            catch (XpsPackagingException xpsException)
            {
                throw xpsException;
            }
        }// end:AddPackageContent()
         //</SnippetXpsCreateAddPkgContent>


        //<SnippetXpsCreateAddDocContent>
        // ------------------------- AddDocumentContent ---------------------------
        /// <summary>
        ///   Adds a predefined set of content to a given document writer.</summary>
        /// <param name="fixedDocumentWriter">
        ///   The document writer to add the content to.</param>
        private void AddDocumentContent(DataTable tb, IXpsFixedDocumentWriter fixedDocumentWriter)
        {
            // Collection of image and font resources used on the current page.
            //   Key: "XpsImage", "XpsFont"
            //   Value: List of XpsImage or XpsFont resources
            Dictionary<string, List<XpsResource>> resources;

            try
            {
                // Add Page 1 to current document.
                IXpsFixedPageWriter fixedPageWriter =
                    fixedDocumentWriter.AddFixedPage();

                // Add the resources for Page 1 and get the resource collection.
                resources = AddPageResources(fixedPageWriter);

                // Write page content for Page 1.
                WritePageContent(tb, fixedPageWriter.XmlWriter, "Page 1 of " + fixedDocumentWriter.Uri.ToString(), resources);

                // Commit Page 1.
                fixedPageWriter.Commit();
                /*
                // Add Page 2 to current document.
                fixedPageWriter = fixedDocumentWriter.AddFixedPage();

                // Add the resources for Page 2 and get the resource collection.
                resources = AddPageResources(fixedPageWriter);

                // Write page content to Page 2.
                WritePageContent(tb, fixedPageWriter.XmlWriter, "Page 2 of " + fixedDocumentWriter.Uri.ToString(), resources);
              
                // Commit Page 2.
                fixedPageWriter.Commit();
                  */
            }
            catch (XpsPackagingException xpsException)
            {
                throw xpsException;
            }
        }// end:AddDocumentContent()
         //</SnippetXpsCreateAddDocContent>


        //<SnippetXpsCreateAddPageResources>
        // -------------------------- AddPageResources ----------------------------
        private Dictionary<string, List<XpsResource>>
                AddPageResources(IXpsFixedPageWriter fixedPageWriter)
        {
            // Collection of all resources for this page.
            //   Key: "XpsImage", "XpsFont"
            //   Value: List of XpsImage or XpsFont
            Dictionary<string, List<XpsResource>> resources =
                new Dictionary<string, List<XpsResource>>();

            // Collections of images and fonts used in the current page.
            List<XpsResource> xpsImages = new List<XpsResource>();
            List<XpsResource> xpsFonts = new List<XpsResource>();

            try
            {
                XpsImage xpsImage;
                XpsFont xpsFont;

                // Add, Write, and Commit image1 to the current page.
                xpsImage = fixedPageWriter.AddImage(XpsImageType.JpegImageType);
                WriteToStream(xpsImage.GetStream(), image1);
                xpsImage.Commit();
                xpsImages.Add(xpsImage);    // Add image1 as a required resource.

                // Add, Write, and Commit font 1 to the current page.
                xpsFont = fixedPageWriter.AddFont();
                WriteObfuscatedStream(
                    xpsFont.Uri.ToString(), xpsFont.GetStream(), font1);
                xpsFont.Commit();
                xpsFonts.Add(xpsFont);      // Add font1 as a required resource.

                // Add, Write, and Commit image2 to the current page.
                xpsImage = fixedPageWriter.AddImage(XpsImageType.TiffImageType);
                WriteToStream(xpsImage.GetStream(), image2);
                xpsImage.Commit();
                xpsImages.Add(xpsImage);    // Add image2 as a required resource.
                xpsImage = fixedPageWriter.AddImage(XpsImageType.TiffImageType);
                WriteToStream(xpsImage.GetStream(), image3);
                xpsImage.Commit();
                xpsImages.Add(xpsImage);    // Add image2 as a required resource.


                // Add, Write, and Commit font2 to the current page.
                xpsFont = fixedPageWriter.AddFont(false);
                WriteToStream(xpsFont.GetStream(), font2);
                xpsFont.Commit();
                xpsFonts.Add(xpsFont);      // Add font2 as a required resource.

                // Return the image and font resources in a combined collection.
                resources.Add("XpsImage", xpsImages);
                resources.Add("XpsFont", xpsFonts);
                return resources;
            }
            catch (XpsPackagingException xpsException)
            {
                throw xpsException;
            }
        }// end:AddPageResources()
         //</SnippetXpsCreateAddPageResources>


        //<SnippetPrinterCapabilities>
        // ---------------------- GetPrintTicketFromPrinter -----------------------
        /// <summary>
        ///   Returns a PrintTicket based on the current default printer.</summary>
        /// <returns>
        ///   A PrintTicket for the current local default printer.</returns>
        private PrintTicket GetPrintTicketFromPrinter()
        {
            PrintQueue printQueue = null;

            LocalPrintServer localPrintServer = new LocalPrintServer();

            // Retrieving collection of local printer on user machine
            PrintQueueCollection localPrinterCollection =
                localPrintServer.GetPrintQueues();

            System.Collections.IEnumerator localPrinterEnumerator =
                localPrinterCollection.GetEnumerator();

            if (localPrinterEnumerator.MoveNext())
            {
                // Get PrintQueue from first available printer
                printQueue = (PrintQueue)localPrinterEnumerator.Current;
            }
            else
            {
                // No printer exist, return null PrintTicket
                return null;
            }

            // Get default PrintTicket from printer
            PrintTicket printTicket = printQueue.DefaultPrintTicket;

            PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();

            // Modify PrintTicket
            if (printCapabilites.CollationCapability.Contains(Collation.Collated))
            {
                printTicket.Collation = Collation.Collated;
            }

            if (printCapabilites.DuplexingCapability.Contains(
                    Duplexing.TwoSidedLongEdge))
            {
                printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
            }

            if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
            {
                printTicket.Stapling = Stapling.StapleDualLeft;
            }

            return printTicket;
        }// end:GetPrintTicketFromPrinter()
         //</SnippetPrinterCapabilities>


        //<SnippetXpsCreateWritePageContent>
        // --------------------------- WritePageContent ---------------------------
        private void WritePageContent(DataTable tb, XmlWriter xmlWriter, string documentUri, Dictionary<string, List<XpsResource>> resources)
        {
            List<XpsResource> xpsImages = resources["XpsImage"];
            List<XpsResource> xpsFonts = resources["XpsFont"];

            // Element are indented for reading purposes only
            xmlWriter.WriteStartElement("FixedPage");
            xmlWriter.WriteAttributeString("Width", "3507");
            xmlWriter.WriteAttributeString("Height", "2480");
            xmlWriter.WriteAttributeString("xmlns",
                "http://schemas.microsoft.com/xps/2005/06");
            xmlWriter.WriteAttributeString("xml:lang", "en-US");

            var query = from DataRow row in tb.AsEnumerable()
                        orderby Convert.ToDecimal(row.Field<string>("ROWNID")),
                       Convert.ToDecimal(row.Field<string>("PRCOND"))
                        select row;
            Rect rect = new Rect(0, 0, 0, 0);
            int myid = 0;

            foreach (DataRow row in query)
            {
                //PRLX	PRLY	PRRX	PRRY	PRLTHICK	PRCTYPE	 	PRFONT	PRFONTSIZE	PRCONTENT
                string PRDES = row["PRDES"].ToString().Trim();
                if (PRDES == "N")
                    continue;
                string text = "";
                double PRLX = double.Parse(row["PRLX"].ToString().Trim());
                double PRLY = double.Parse(row["PRLY"].ToString().Trim());
                double PRRX = double.Parse(row["PRRX"].ToString().Trim());
                double PRRY = double.Parse(row["PRRY"].ToString().Trim());
                double PRCOND = double.Parse(row["PRCOND"].ToString().Trim());
                string PRLTHICK = row["PRLTHICK"].ToString().Trim();
                string PRCTYPE = row["PRCTYPE"].ToString().Trim();
                string PRFONT = Helpers.Helper.GetGB2312Value(row["PRFONT"].ToString().Trim());
                string PRFONTSIZE = row["PRFONTSIZE"].ToString().Trim();
                string PRCONTENT = Helpers.Helper.GetGB2312Value(row["PRCONTENT"].ToString());
                string PRCONTDES = Helpers.Helper.GetGB2312Value(row["PRCONTDES"].ToString());
                double lineheight = 120 * 8 / 48;
                //PRLY = PRCOND * lineheight;
                //PRLX = PRLX * lineheight;
                //double x = WPFDpi * PRLX / cPaper.PCLUnit;
                //double y = WPFDpi * PRLY / cPaper.PCLUnit;
                switch (PRCTYPE)
                {
                    case "Paper":
                        break;
                    case "TXT":
                        /*    double fsize = 12.0;
                       //Typeface tp = new Typeface(this.FontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch());
                       var qf = from DataRow rf in tb.AsEnumerable()
                                where rf["PRLY"].ToString() == PRFONT
                                select rf;
                       foreach (DataRow rf in qf)
                       {

                           string ff = rf["PRCTYPDES"].ToString();
                           if (ff == "") ff = "LetterGothic";
                           tp = GetFontFaimily(ff);
                           string[] finfo = rf["PRCONTENT"].ToString().Split(';');
                           if (finfo.Length < 5) continue;
                           //cFont.SymbolSet + ";" + cFont.Typeface + ";" + cFont.FontWeight + ";" + cFont.FontStyle + ";" + cFont.FontPitch + ";" + cFont.FontSpacing;
                           //300/1.5/10 cPaper.PCLUnit * 2.54 / cFont.FontPitch
                           if (finfo[4] == "") continue;
                           fsize = Convert.ToInt16(WPFDpi * 2.54 / double.Parse(finfo[4]));
                           //PCL Def charactors per inch
                           //windows each fonts how many pixels;
                           switch (finfo[3])
                           {
                               case "0":
                                   break;
                           }
                           switch (finfo[2])
                           {
                               case "0":
                                   tp = new Typeface(tp.FontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch());
                                   break;
                               case "1":
                                   tp = new Typeface(tp.FontFamily, FontStyles.Normal, FontWeights.Medium, new FontStretch());
                                   break;
                               case "2":
                                   tp = new Typeface(tp.FontFamily, FontStyles.Normal, FontWeights.Bold, new FontStretch());
                                   break;
                           }
                       }

                    */
                        xmlWriter.WriteStartElement("Glyphs");
                        xmlWriter.WriteAttributeString("Fill", "#ff000000");
                        xmlWriter.WriteAttributeString(
                            "FontUri", xpsFonts[1].Uri.ToString());
                        xmlWriter.WriteAttributeString("FontRenderingEmSize", "16");
                        xmlWriter.WriteAttributeString("OriginX", PRLX.ToString());
                        xmlWriter.WriteAttributeString("OriginY", PRLY.ToString());
                        xmlWriter.WriteAttributeString(
                            "UnicodeString", PRCONTENT);
                        xmlWriter.WriteEndElement();

                        break;
                    case "RECT":

                        Rect rectangle = new Rect();
                        string[] rects = PRCONTENT.Split(';');
                        if (rects.Length < 5) continue;
                        /*rectangle.X = WPFDpi * double.Parse(rects[0]) / cPaper.PCLUnit;
                        rectangle.Y = WPFDpi * double.Parse(rects[1]) / cPaper.PCLUnit;
                        rectangle.Width = WPFDpi * double.Parse(rects[2]) / cPaper.PCLUnit;
                        rectangle.Height = WPFDpi * double.Parse(rects[3]) / cPaper.PCLUnit;
                        System.Windows.Media.Pen pen = new System.Windows.Media.Pen(System.Windows.Media.Brushes.Black, WPFDpi * double.Parse(rects[4]) / cPaper.PCLUnit);
                        */
                        double rx = double.Parse(rects[0]);
                        double ry = double.Parse(rects[1]);
                        double width = double.Parse(rects[2]);
                        double height = double.Parse(rects[3]);
                        PathFigure pf = new PathFigure();
                        pf.StartPoint = new Point(rx, ry);
                        pf.IsClosed = true;
                        PolyLineSegment pl = new PolyLineSegment();
                        pl.Points.Add(new Point(rx, ry + height));
                        pl.Points.Add(new Point(rx + width, ry + height));
                        pl.Points.Add(new Point(rx + width, ry));
                        pf.Segments = new PathSegmentCollection() { pl };
                        xmlWriter.WriteStartElement("Path");
                        xmlWriter.WriteAttributeString("Data", pf.ToString().Replace("M", "M ").Replace("L", " L").Replace("z", " z"));// "M 120, 357 L 324, 357 324, 510 120, 510 z");
                        xmlWriter.WriteStartElement("Path.Fill");
                        xmlWriter.WriteStartElement("ImageBrush");
                        xmlWriter.WriteAttributeString("ImageSource", xpsImages[2].Uri.ToString());
                        //xmlWriter.WriteAttributeString("Viewbox", "0,0,181,134");
                        xmlWriter.WriteAttributeString("Viewbox", rx + "," + ry + "," + width + "," + height);
                        xmlWriter.WriteAttributeString("TileMode", "Tile");
                        xmlWriter.WriteAttributeString("ViewboxUnits", "Absolute");
                        xmlWriter.WriteAttributeString("ViewportUnits", "Absolute");
                        xmlWriter.WriteAttributeString("Viewport", rx + "," + ry + "," + width + "," + height);
                        xmlWriter.WriteEndElement();//ImageBrush
                        xmlWriter.WriteEndElement();//Fill
                        xmlWriter.WriteEndElement(); //Path
                        break;
                }

                //PathGeometry pg = new PathGeometry();

            }


            /*
             * xmlWriter.WriteStartElement("Path");
                xmlWriter.WriteAttributeString(
                    "Data", "M 120,357 L 324,357 324,510 120,510 z");
                xmlWriter.WriteStartElement("Path.Fill");
                    xmlWriter.WriteStartElement("ImageBrush");
                        xmlWriter.WriteAttributeString(
                            "ImageSource", xpsImages[1].Uri.ToString());
                        xmlWriter.WriteAttributeString(                            "Viewbox", "0,0,204,153");
                        xmlWriter.WriteAttributeString(
                            "TileMode", "None");
                        xmlWriter.WriteAttributeString(
                            "ViewboxUnits", "Absolute");
                        xmlWriter.WriteAttributeString(
                            "ViewportUnits", "Absolute");
                        mlWriter.WriteAttributeString(                            "Viewport", "120,357,204,153");
                    xmlWriter.WriteEndElement();

                xmlWriter.WriteEndElement();
            xmlWriter.WriteEndElement();
            xmlWriter.WriteStartElement("Path");
            xmlWriter.WriteAttributeString("Data", "M 120,187 L 301,187 301,321 120,321 z");
            xmlWriter.WriteStartElement("Path.Fill");
            xmlWriter.WriteStartElement("ImageBrush");
            xmlWriter.WriteAttributeString("ImageSource", xpsImages[0].Uri.ToString());
            xmlWriter.WriteAttributeString( "Viewbox", "0,0,181,134");
            xmlWriter.WriteAttributeString("TileMode", "None");
            xmlWriter.WriteAttributeString( "ViewboxUnits", "Absolute");
            xmlWriter.WriteAttributeString(
                "ViewportUnits", "Absolute");
            xmlWriter.WriteAttributeString( "Viewport", "120,187,181,134");
            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndElement();

         */

        }// end:WritePageContent()
         //<SnippetXpsCreateWritePageContent>


        // ----------------------------- WriteToStream ----------------------------
        private void WriteToStream(Stream stream, string resource)
        {
            const int bufSize = 0x1000;
            byte[] buf = new byte[bufSize];
            int bytesRead = 0;

            using (FileStream fileStream =
                new FileStream(resource, FileMode.Open, FileAccess.Read))
            {
                while ((bytesRead = fileStream.Read(buf, 0, bufSize)) > 0)
                {
                    stream.Write(buf, 0, bytesRead);
                }
            }
        }// end:WriteToStream()


        // ------------------------- WriteObfuscatedStream ------------------------
        private void WriteObfuscatedStream(
            string resourceName, Stream stream, string resource)
        {
            int bufSize = 0x1000;
            int guidByteSize = 16;
            int obfuscatedByte = 32;

            // Get the GUID byte from the resource name.  Typical Font name:
            //    /Resources/Fonts/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ODTTF
            int startPos = resourceName.LastIndexOf('/') + 1;
            int length = resourceName.LastIndexOf('.') - startPos;
            resourceName = resourceName.Substring(startPos, length);

            Guid guid = new Guid(resourceName);

            string guidString = guid.ToString("N");

            // Parsing the guid string and coverted into byte value
            byte[] guidBytes = new byte[guidByteSize];
            for (int i = 0; i < guidBytes.Length; i++)
            {
                guidBytes[i] = Convert.ToByte(guidString.Substring(i * 2, 2), 16);
            }

            using (FileStream filestream = new FileStream(resource, FileMode.Open))
            {
                // XOR the first 32 bytes of the source
                // resource stream with GUID byte.
                byte[] buf = new byte[obfuscatedByte];
                filestream.Read(buf, 0, obfuscatedByte);

                for (int i = 0; i < obfuscatedByte; i++)
                {
                    int guidBytesPos = guidBytes.Length - (i % guidBytes.Length) - 1;
                    buf[i] ^= guidBytes[guidBytesPos];
                }
                stream.Write(buf, 0, obfuscatedByte);

                // copy remaining stream from source without obfuscation
                buf = new byte[bufSize];

                int bytesRead = 0;
                while ((bytesRead = filestream.Read(buf, 0, bufSize)) > 0)
                {
                    stream.Write(buf, 0, bytesRead);
                }
            }
        }// end:WriteObfuscatedStream()

    }

    public partial class TPCLTOOLS
    {
        public XpsDocument Convert2XPS(DataTable tb)
        {
            XpsCreate xpsCreate = new XpsCreate();
            return  xpsCreate.Run(tb);
        }

    }

    // end:class XpsCreate
    /*
    public partial class TPCLTOOLS
    {
        string packageWithPrintTicketName = @"D:\ITXRPRT\Documents\Print\XpsDocument-withPrintTicket.xps";
        string packageName = @"D:\ITXRPRT\Documents\Print\XpsDocument.xps"; // (without PrintTicket)
        string image1 = @"D:\ITXRPRT\Documents\Images\picture.jpg";
        string image2 = @"D:\ITXRPRT\Documents\Images\image.tif";
        string font1 = @"D:\urwfonts\LetterGothic-Bol.ttf";
        string font2 = @"D:\urwfonts\CenturySchL-Bold.ttf";
        string fontContentType =
            "application/vnd.ms-package.obfuscated-opentype";
        // ------------------------- AddDocumentContent ---------------------------
        /// <summary>
        ///   Adds a predefined set of content to a given document writer.</summary>
        /// <param name="fixedDocumentWriter">
        ///   The document writer to add the content to.</param>
        private void AddDocumentContent(DataTable tb, IXpsFixedDocumentWriter fixedDocumentWriter)
        {
            // Collection of image and font resources used on the current page.
            //   Key: "XpsImage", "XpsFont"
            //   Value: List of XpsImage or XpsFont resources
            Dictionary<string, List<XpsResource>> resources;

            try
            {
                // Add Page 1 to current document.
                IXpsFixedPageWriter fixedPageWriter =
                    fixedDocumentWriter.AddFixedPage();

                // Add the resources for Page 1 and get the resource collection.
                resources = AddPageResources(fixedPageWriter);

                // Write page content for Page 1.
                WritePageContent(tb, fixedPageWriter.XmlWriter, "Page 1 of " + fixedDocumentWriter.Uri.ToString(), resources);

                // Commit Page 1.
                fixedPageWriter.Commit();

            }
            catch (XpsPackagingException xpsException)
            {
                throw xpsException;
            }
        }// end:AddDocumentContent()
         //<SnippetXpsCreateAddPageResources>
         // -------------------------- AddPageResources ----------------------------
        private Dictionary<string, List<XpsResource>> AddPageResources(IXpsFixedPageWriter fixedPageWriter)
        {
            // Collection of all resources for this page.
            //   Key: "XpsImage", "XpsFont"
            //   Value: List of XpsImage or XpsFont
            Dictionary<string, List<XpsResource>> resources =
                new Dictionary<string, List<XpsResource>>();

            // Collections of images and fonts used in the current page.
            List<XpsResource> xpsImages = new List<XpsResource>();
            List<XpsResource> xpsFonts = new List<XpsResource>();

            try
            {
                XpsImage xpsImage;
                XpsFont xpsFont;

                // Add, Write, and Commit image1 to the current page.
                xpsImage = fixedPageWriter.AddImage(XpsImageType.JpegImageType);
                WriteToStream(xpsImage.GetStream(), image1);
                xpsImage.Commit();
                xpsImages.Add(xpsImage);    // Add image1 as a required resource.

                // Add, Write, and Commit font 1 to the current page.
                xpsFont = fixedPageWriter.AddFont();
                WriteObfuscatedStream(
                    xpsFont.Uri.ToString(), xpsFont.GetStream(), font1);
                xpsFont.Commit();
                xpsFonts.Add(xpsFont);      // Add font1 as a required resource.

                // Add, Write, and Commit image2 to the current page.
                xpsImage = fixedPageWriter.AddImage(XpsImageType.TiffImageType);
                WriteToStream(xpsImage.GetStream(), image2);
                xpsImage.Commit();
                xpsImages.Add(xpsImage);    // Add image2 as a required resource.

                // Add, Write, and Commit font2 to the current page.
                xpsFont = fixedPageWriter.AddFont(false);
                WriteToStream(xpsFont.GetStream(), font2);
                xpsFont.Commit();
                xpsFonts.Add(xpsFont);      // Add font2 as a required resource.

                // Return the image and font resources in a combined collection.
                resources.Add("XpsImage", xpsImages);
                resources.Add("XpsFont", xpsFonts);
                return resources;
            }
            catch (XpsPackagingException xpsException)
            {
                throw xpsException;
            }
        }// end:AddPageResources()
         //</SnippetXpsCreateAddPageResources>


        //<SnippetPrinterCapabilities>
        //</SnippetXpsCreateAddDocContent>
        //<SnippetPrinterCapabilities>
        // ---------------------- GetPrintTicketFromPrinter -----------------------
        /// <summary>
        ///   Returns a PrintTicket based on the current default printer.</summary>
        /// <returns>
        ///   A PrintTicket for the current local default printer.</returns>
        private PrintTicket GetPrintTicketFromPrinter()
        {
            PrintQueue printQueue = null;

            LocalPrintServer localPrintServer = new LocalPrintServer();

            // Retrieving collection of local printer on user machine
            PrintQueueCollection localPrinterCollection =
                localPrintServer.GetPrintQueues();

            System.Collections.IEnumerator localPrinterEnumerator =
                localPrinterCollection.GetEnumerator();

            if (localPrinterEnumerator.MoveNext())
            {
                // Get PrintQueue from first available printer
                printQueue = (PrintQueue)localPrinterEnumerator.Current;
            }
            else
            {
                // No printer exist, return null PrintTicket
                return null;
            }

            // Get default PrintTicket from printer
            PrintTicket printTicket = printQueue.DefaultPrintTicket;

            PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();

            // Modify PrintTicket
            if (printCapabilites.CollationCapability.Contains(Collation.Collated))
            {
                printTicket.Collation = Collation.Collated;
            }

            if (printCapabilites.DuplexingCapability.Contains(
                    Duplexing.TwoSidedLongEdge))
            {
                printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
            }

            if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
            {
                printTicket.Stapling = Stapling.StapleDualLeft;
            }

            return printTicket;
        }// end:GetPrintTicketFromPrinter()
         //</SnippetPrinterCapabilities>


        //<SnippetXpsCreateWritePageContent>
        // --------------------------- WritePageContent ---------------------------
        private void WritePageContent(DataTable tb, XmlWriter xmlWriter, string documentUri, Dictionary<string, List<XpsResource>> resources)
        {
            List<XpsResource> xpsImages = resources["XpsImage"];
            List<XpsResource> xpsFonts = resources["XpsFont"];
            /*
            // Element are indented for reading purposes only
            xmlWriter.WriteStartElement("FixedPage");
            xmlWriter.WriteAttributeString("Width", cPaper.Width300DPI.ToString());
            xmlWriter.WriteAttributeString("Height", cPaper.Height300DPI.ToString());
            xmlWriter.WriteAttributeString("xmlns", "http://schemas.microsoft.com/xps/2005/06");
            xmlWriter.WriteAttributeString("xml:lang", "en-US");
   xmlWriter.WriteStartElement("FixedPage");
           xmlWriter.WriteAttributeString("Width", "816");
           xmlWriter.WriteAttributeString("Height", "1056");
           xmlWriter.WriteAttributeString("xmlns",
               "http://schemas.microsoft.com/xps/2005/06");
           xmlWriter.WriteAttributeString("xml:lang", "en-US");

           FormattedText str = null;
           var query = from DataRow row in TBMain.AsEnumerable()
                       orderby Convert.ToDecimal(row.Field<string>("ROWNID")),
                      Convert.ToDecimal(row.Field<string>("PRCOND"))
                       select row;
           Rect rect = new Rect(0, 0, 0, 0);
           foreach (DataRow row in query)
           {
               //PRLX	PRLY	PRRX	PRRY	PRLTHICK	PRCTYPE	 	PRFONT	PRFONTSIZE	PRCONTENT
               string PRDES = row["PRDES"].ToString().Trim();
               if (PRDES == "N")
                   continue;
               string text = "";
               double PRLX = double.Parse(row["PRLX"].ToString().Trim());
               double PRLY = double.Parse(row["PRLY"].ToString().Trim());
               double PRRX = double.Parse(row["PRRX"].ToString().Trim());
               double PRRY = double.Parse(row["PRRY"].ToString().Trim());
               double PRCOND = double.Parse(row["PRCOND"].ToString().Trim());
               string PRLTHICK = row["PRLTHICK"].ToString().Trim();
               string PRCTYPE = row["PRCTYPE"].ToString().Trim();
               string PRFONT = Helpers.Helper.GetGB2312Value(row["PRFONT"].ToString().Trim());
               string PRFONTSIZE = row["PRFONTSIZE"].ToString().Trim();
               string PRCONTENT = Helpers.Helper.GetGB2312Value(row["PRCONTENT"].ToString());
               string PRCONTDES = Helpers.Helper.GetGB2312Value(row["PRCONTDES"].ToString());
               //PRLY = PRCOND * lineheight;
               //PRLX = PRLX * lineheight;
               double x = WPFDpi * PRLX / cPaper.PCLUnit;
               double y = WPFDpi * PRLY / cPaper.PCLUnit;
               switch (PRCTYPE)
               {
                   case "Paper":
                       break;
                   case "TXT":
                       double fsize = 12.0;
                       Typeface tp = new Typeface(this.FontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch());
                       var qf = from DataRow rf in TBMain.AsEnumerable()
                                where rf["PRLY"].ToString() == PRFONT
                                select rf;
                       foreach (DataRow rf in qf)
                       {
                           string ff = rf["PRCTYPDES"].ToString();
                           if (ff == "") ff = "LetterGothic";
                           tp = GetFontFaimily(ff);
                           string[] finfo = rf["PRCONTENT"].ToString().Split(';');
                           if (finfo.Length < 5) continue;
                           //cFont.SymbolSet + ";" + cFont.Typeface + ";" + cFont.FontWeight + ";" + cFont.FontStyle + ";" + cFont.FontPitch + ";" + cFont.FontSpacing;
                           //300/1.5/10 cPaper.PCLUnit * 2.54 / cFont.FontPitch
                           if (finfo[4] == "") continue;
                           fsize = Convert.ToInt16(WPFDpi * 2.54 / double.Parse(finfo[4]));
                           //PCL Def charactors per inch
                           //windows each fonts how many pixels;
                           switch (finfo[3])
                           {
                               case "0":
                                   break;
                           }
                           switch (finfo[2])
                           {
                               case "0":
                                   tp = new Typeface(tp.FontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch());
                                   break;
                               case "1":
                                   tp = new Typeface(tp.FontFamily, FontStyles.Normal, FontWeights.Medium, new FontStretch());
                                   break;
                               case "2":
                                   tp = new Typeface(tp.FontFamily, FontStyles.Normal, FontWeights.Bold, new FontStretch());
                                   break;
                           }
                       }


                       WriteText(xmlWriter, PRCONTENT, PRLX.ToString(), PRLY.ToString(), fsize.ToString(), xpsFonts[0].Uri.ToString());

                       break;
                   case "RECT":
                       Rect rectangle = new Rect();
                       string[] rects = PRCONTENT.Split(';');
                       if (rects.Length < 5) continue;
                       rectangle.X = WPFDpi * double.Parse(rects[0]) / cPaper.PCLUnit;
                       rectangle.Y = WPFDpi * double.Parse(rects[1]) / cPaper.PCLUnit;
                       rectangle.Width = WPFDpi * double.Parse(rects[2]) / cPaper.PCLUnit;
                       rectangle.Height = WPFDpi * double.Parse(rects[3]) / cPaper.PCLUnit;
                       WritePath(xmlWriter, "", PRLX.ToString(), PRLY.ToString());
                       break;
               }
           }

           xmlWriter.WriteEndElement();
           xmlWriter.WriteEndElement();

           xmlWriter.WriteEndElement();
           xmlWriter.WriteEndElement();
           xmlWriter.WriteEndElement();
           xmlWriter.WriteEndElement();
       }
       public void WriteText(XmlWriter xmlWriter, string content, string x, string y, string fontsize, string fonturi)
       {
           xmlWriter.WriteStartElement("Glyphs");
           xmlWriter.WriteAttributeString("Fill", "#ff000000");
           xmlWriter.WriteAttributeString("FontUri", fonturi);
           xmlWriter.WriteAttributeString("FontRenderingEmSize", fontsize);
           /*xmlWriter.WriteAttributeString("OriginX", x);
           xmlWriter.WriteAttributeString("OriginY", y);
           xmlWriter.WriteAttributeString("OriginX", "120");
           xmlWriter.WriteAttributeString("OriginY", "110");
           xmlWriter.WriteAttributeString("UnicodeString", content);
           xmlWriter.WriteEndElement();
       }
       public void WritePath(XmlWriter xmlWriter, string content, string x, string y)
       {
           xmlWriter.WriteStartElement("Path");
           xmlWriter.WriteAttributeString("Data", "M 120,357 L 324,357 324,510 120,510 z");
           xmlWriter.WriteStartElement("Path.Fill");
           xmlWriter.WriteStartElement("ImageBrush");
           xmlWriter.WriteAttributeString("ImageSource", content);
           xmlWriter.WriteAttributeString("Viewbox", "0,0,204,153");
           xmlWriter.WriteAttributeString("TileMode", "None");
           xmlWriter.WriteAttributeString("ViewboxUnits", "Absolute");
           xmlWriter.WriteAttributeString("ViewportUnits", "Absolute");
           xmlWriter.WriteAttributeString("Viewport", "120,357,204,153");
       }
       private void WriteToStream(Stream stream, string resource)
       {
           const int bufSize = 0x1000;
           byte[] buf = new byte[bufSize];
           int bytesRead = 0;

           using (FileStream fileStream =
               new FileStream(resource, FileMode.Open, FileAccess.Read))
           {
               while ((bytesRead = fileStream.Read(buf, 0, bufSize)) > 0)
               {
                   stream.Write(buf, 0, bytesRead);
               }
           }
       }// end:WriteToStream()


       // ------------------------- WriteObfuscatedStream ------------------------
       private void WriteObfuscatedStream(
           string resourceName, Stream stream, string resource)
       {
           int bufSize = 0x1000;
           int guidByteSize = 16;
           int obfuscatedByte = 32;

           // Get the GUID byte from the resource name.  Typical Font name:
           //    /Resources/Fonts/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ODTTF
           int startPos = resourceName.LastIndexOf('/') + 1;
           int length = resourceName.LastIndexOf('.') - startPos;
           resourceName = resourceName.Substring(startPos, length);

           Guid guid = new Guid(resourceName);

           string guidString = guid.ToString("N");

           // Parsing the guid string and coverted into byte value
           byte[] guidBytes = new byte[guidByteSize];
           for (int i = 0; i < guidBytes.Length; i++)
           {
               guidBytes[i] = Convert.ToByte(guidString.Substring(i * 2, 2), 16);
           }

           using (FileStream filestream = new FileStream(resource, FileMode.Open))
           {
               // XOR the first 32 bytes of the source
               // resource stream with GUID byte.
               byte[] buf = new byte[obfuscatedByte];
               filestream.Read(buf, 0, obfuscatedByte);

               for (int i = 0; i < obfuscatedByte; i++)
               {
                   int guidBytesPos = guidBytes.Length - (i % guidBytes.Length) - 1;
                   buf[i] ^= guidBytes[guidBytesPos];
               }
               stream.Write(buf, 0, obfuscatedByte);

               // copy remaining stream from source without obfuscation
               buf = new byte[bufSize];

               int bytesRead = 0;
               while ((bytesRead = filestream.Read(buf, 0, bufSize)) > 0)
               {
                   stream.Write(buf, 0, bytesRead);
               }
           }
       }// end:WriteObfuscatedStream()
       private void AddPackageContent(DataTable tb, XpsDocument xpsDocument, bool attachPrintTicket)
       {
           try
           {
               PrintTicket printTicket = GetPrintTicketFromPrinter();
               // PrintTicket is null, there is no need to attach one.
               if (printTicket == null)
                   attachPrintTicket = false;

               // Add a FixedDocumentSequence at the Package root
               IXpsFixedDocumentSequenceWriter documentSequenceWriter = xpsDocument.AddFixedDocumentSequence();

               // Add the 1st FixedDocument to the FixedDocumentSequence. - - - - -
               IXpsFixedDocumentWriter fixedDocumentWriter = documentSequenceWriter.AddFixedDocument();

               // Add content to the 1st document
               AddDocumentContent(tb, fixedDocumentWriter);
               // Commit the 1st Document
               fixedDocumentWriter.Commit(); 

               // If attaching PrintTickets, attach one at
               // the package FixedDocumentSequence level.
               if (attachPrintTicket)
                   documentSequenceWriter.PrintTicket = printTicket;

               // Commit the FixedDocumentSequence
               documentSequenceWriter.Commit();
           }
           catch (XpsPackagingException xpsException)
           {
               throw xpsException;
           }
       }

       public void Convert2XPS(DataTable tb)
       {
           if (File.Exists(packageName))
               File.Delete(packageName);
           using (Package package = Package.Open(packageName))
           {
               XpsDocument xpsDocument = new XpsDocument(package);

               // Add the package content (false=without PrintTicket).
               AddPackageContent(tb, xpsDocument, false); 
               // Close the package.
               xpsDocument.Close();
           }  
       }
   }*/

}
